home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
telecomm
/
sticpsrc.lzh
/
SOURCE.ARC
/
NR3.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-07-25
|
35KB
|
1,203 lines
/* NET/ROM level 3 low level processing */
#include <stdio.h>
#include "global.h"
#include "mbuf.h"
#include "iface.h"
#include "trace.h"
#include "timer.h"
#include "arp.h"
#include "slip.h"
#include "ax25.h"
#include "netrom.h"
#include "lapb.h"
#include "ip.h"
#include <ctype.h>
struct nrnbr_tab *nrnbr_tab[NRNUMCHAINS];
struct nrroute_tab *nrroute_tab[NRNUMCHAINS];
struct nrnf_tab *nrnf_tab[NRNUMCHAINS];
struct ax25_call *nr_excl[NHASH];
/* netrom level 3 params */
unsigned nr_autofloor = 1;
unsigned nr_maxfail = 1;
unsigned nr_maxqueue = 16;
unsigned nr_maxroutes = 3;
unsigned nr_nfmode = NRNF_NOFILTER;
unsigned nr_tcpip = NRT_NORM;
unsigned nr_ttl = 10;
unsigned obso_init = 6;
unsigned obso_minbc = 5;
char nr_aliasip[] = NR_TCPIP;
struct interface *nr_interface;
struct ax25_addr nr_nodebc;
static struct nrnf_tab *find_nrnf();
static struct ax25_addr *find_nbrif ();
static int alt_route();
/* Send datagrams across a NET/ROM network connection */
void
nr_send3(bp,dest)
struct mbuf *bp;
struct ax25_addr *dest;
{
struct nr3hdr n3hdr;
void nr__route();
n3hdr.source.call[0] = '\0'; /* source call to be filled in */
memcpy(&n3hdr.dest,dest,sizeof(struct ax25_addr));
n3hdr.ttl = nr_ttl;
nr__route(&n3hdr,bp,NULLAXADDR);/* pass off to level 3 routing code */
}
/* Figure out if a call is assigned to one of my NET/ROM
* interfaces.
*/
int
ismycall(addr)
struct ax25_addr *addr;
{
register struct interface *ifp;
if (nr_interface != NULLIF && nr_interface->hwaddr != NULLCHAR)
return addreq((struct ax25_addr *)(nr_interface->hwaddr),addr);
for (ifp = ifaces; ifp != NULLIF; ifp = ifp->next)
if (ifp->nriface != NULLNRIFACE &&
addreq((struct ax25_addr *)(ifp->hwaddr),addr)) {
return 1;
}
return 0;
}
/* Determine the netrom source call to be used (global or interface) */
struct ax25_addr *
nr_scall (ifp)
struct interface *ifp;
{
if (nr_interface->hwaddr != NULLCHAR)
return (struct ax25_addr *)nr_interface->hwaddr;
else
return (struct ax25_addr *)ifp->hwaddr;
}
/* Route NET/ROM network layer packets.
* This function is called for NET/ROM packets incoming on AX.25 interfaces.
*/
void
nr_route(axp,bp)
struct ax25_cb *axp; /* receiving AX.25 connection */
struct mbuf *bp; /* incoming NET/ROM packet */
{
struct nr3hdr n3hdr;
int i;
char *cp,*putaxaddr();
struct nrroute_tab *rp;
char neighbor[3 * AXALEN];
if (axp->interface->nriface == NULLNRIFACE || /* not NET/ROM iface? */
!ismycall(&axp->addr.source) || /* bad call? */
ntohnr3(&n3hdr,&bp) < 0 || /* header bad? */
valid_addr(&n3hdr.source) != 0) { /* illegal source? */
free_p(bp);
return;
}
/* a real NET/ROM does not like to be polled using I(P) frames */
/* set the pthresh to zero when a connection apparently is from */
/* a NET/ROM neighbor, to prevent trouble. we will use RR(P). */
axp->pthresh = 0;
/* when filtermode "exclusive" is selected, we only want to route */
/* netrom traffic from nodes in our filter table. check if the */
/* callsign sending the packet (axp->addr.dest) is in the table. */
if (nr_nfmode == NRNF_EXCLUSIVE &&
find_nrnf(&axp->addr.dest,axp->interface) == NULLNRNFTAB) {
free_p(bp); /* not in list, discard packet */
return;
}
/* when we receive something from a node, be certain a route */
/* exists to that node. if not, create a route from information */
/* in the incoming packet. this is done to make sure a retour */
/* route exists when a response packet has to be sent. */
if (((rp = find_nrroute(&n3hdr.source)) == NULLNRRTAB ||
rp->routes == NULLNRBIND || rp->routes->quality == 0) &&
!ismycall(&n3hdr.source) &&
axp->addr.ndigis < 3) /* required by NET/ROM... */
{
cp = putaxaddr(neighbor,&axp->addr.dest);
for (i = 0; i < axp->addr.ndigis; i++){
cp[-1] &= ~E;
cp = putaxaddr(cp,&axp->addr.digis[i]);
}
cp[-1] |= E;
nr_rt_add(NULLCHAR, /* don't know alias */
&n3hdr.source, /* dest=source node from l3 hdr */
axp->interface, /* receiving interface */
1, /* a low quality (but >0) */
obso_init,
neighbor, /* path to source */
0); /* treat like broadcast info */
}
nr__route(&n3hdr,bp,&axp->addr.dest);
}
/* Same, but header already extracted */
/* Used by nr_route(), and also for outgoing NET/ROM packets. */
void
nr__route(hdr,bp,source)
struct nr3hdr *hdr;
struct mbuf *bp;
struct ax25_addr *source;
{
struct ax25_cb *axp,*find_ax25(),*open_ax25();
struct ax25 naxhdr;
struct ax25_addr neighbor,*scall;
struct mbuf *hbp,*pbp;
register struct nrnbr_tab *np;
register struct nrroute_tab *rp;
int route_tries;
extern int16 axwindow;
#ifdef OLD_NETROM
unsigned char nr4head[NR4HLEN];
#endif
void ax_incom(),nr3_state();
/* check if the packet is addressed to one of our NET/ROM calls */
/* if so, bump it up to either NET/ROM level 4, or to IP */
if (ismycall(&hdr->dest)) {
/* trace input from "netrom" fake interface */
dump(nr_interface,IF_TRACE_IN,TRACE_NETROM,bp);
/* check if it is from me. if so, it is a routing loop! */
if (hdr->source.call[0] == '\0' || ismycall(&hdr->source)){
free_p(bp);
return;
}
#ifdef OLD_NETROM
/* these statements check if the packet is a NET/ROM transport
layer packet, or an IP packet passed over the NET/ROM network
layer. checks applied are:
- first byte does not look like an IP Version/IHL byte
- byte 4 is a valid NET/ROM transport layer opcode
boy is this awful! who invented this way of sending IP
packets over NET/ROM???!!
fortunately, a new method is to use NET/ROM opcode 0 to
encapsulate an IP packet. the old one is still preserved
in the name of backward-compatability. (if OLD_NETROM defined)
*/
if (pullup(&bp,nr4head,NR4HLEN) != NR4HLEN)
return; /* very small packet, cannot be valid */
if ((hbp = pushdown(bp,NR4HLEN)) == NULLBUF){ /* put the header back on */
free_p(bp);
return;
}
memcpy(hbp->data,nr4head,NR4HLEN);
if ((nr4head[0] & 0xf0) != (IPVERSION << 4) &&
(nr4head[4] & NR4OMASK) <= NR4INFACK){
nr4recv(hbp); /* send to NET/ROM transport */
} else {
ip_route(hbp,0); /* it may be an IP packet */
}
#else
nr4recv(bp); /* always send to NET/ROM transport */
#endif
return;
}
if (--(hdr->ttl) == 0) { /* the packet's time to live is over! */
free_p(bp);
return;
}
if ((rp = find_nrroute(&hdr->dest)) == NULLNRRTAB) {
/* no route, drop the packet */
free_p(bp);
return;
}
route_tries = nr_maxroutes;
while (route_tries)
{
if (rp->routes == NULLNRBIND) {
/* This shouldn't happen yet, but might if we add */
/* dead route detection */
free_p(bp);
return;
}
np = rp->routes->via;
getaxaddr(&neighbor,np->call);
/* check if we are going to send the packet back to the neighbor */
/* that just sent it to us. if so, there apparently exists no */
/* usable route to the destination from there, and we better try */
/* an alternative route */
if (source != NULLAXADDR && addreq(source,&neighbor)){
if (alt_route(rp) < 0) /* one route only */
break;
route_tries--;
} else {
break;
}
}
scall = nr_scall(np->interface); /* get netrom call */
/* Now check to see if the source call is null. That is */
/* a signal from nr_send that the packet originates here,*/
/* so we need to insert the callsign of the appropriate */
/* interface. this will be the global NET/ROM callsign */
/* if available, else the callsign for the interface */
if (hdr->source.call[0] == '\0')
memcpy(&hdr->source,scall,AXALEN);
/* Make sure there is a connection to the neighbor */
if ((axp = find_ax25(&neighbor,scall)) == NULLAX25 ||
(axp->state != CONNECTED && axp->state != SETUP)) {
/* Open a new connection or reinitiali